package com.tnovoselec.android.feed.handler;

import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.os.SystemClock;
import android.util.Log;

import com.tnovoselec.android.favorites.entity.EnclosureFavoritesDto;
import com.tnovoselec.android.favorites.entity.NewsFavoritesDto;

public class NewsParser extends DefaultHandler {

	private static final String TAG_ITEM = "item";
	private static final String TAG_LINK = "link";
	private static final String TAG_GUID = "guid";
	private static final String TAG_AUTHOR = "author";
	private static final String TAG_LAST_BUILD_DATE = "lastBuildDate";
	private static final String TAG_CONTENT = "content";
	private static final String TAG_TITLE = "title";
	private static final String TAG_PUBDATE = "pubDate";
	private static final String TAG_PUBLISHED = "published";
	private static final String TAG_DESCRIPTION = "description";
	private static final String TAG_ENCLOSURE = "enclosure";
	private static final String TAG_PROPERTY = "property";
	private static final String TAG_RELATED_ARTICLE = "relatedArticleGuid";
	private static final String TAG_COMMENTS_LINK = "comments";

	private static final String ATTR_TITLE = "title";
	private static final String ATTR_URL = "url";
	private static final String ATTR_DESCRITPION = "description";
	private static final String ATTR_THUMBURL = "thumburl";
	private static final String ATTR_MIME_TYPE = "type";
	private static final String ATTR_LENGTH = "length";
	private static final String ATTR_KEY = "key";

	private boolean inItem = false;
	private boolean inLink = false;
	private boolean inGuid = false;
	private boolean inAuthor = false;
	private boolean inLastBuildDate = false;
	private boolean inContent = false;
	private boolean inPubdate = false;
	private boolean inTitle = false;
	private boolean inDescription = false;
	private boolean inCommentsLink = false;
	private boolean inEnclosure = false;
	private boolean inProperty = false;
	private boolean inRelatedArticle = false;

	private List<NewsFavoritesDto> news = new ArrayList<NewsFavoritesDto>();
	private List<EnclosureFavoritesDto> enclosures = new ArrayList<EnclosureFavoritesDto>();

	private NewsFavoritesDto item;
	private EnclosureFavoritesDto enclosure;

	private StringBuilder buffer;

	private String currentPropertyKey;

	private long parsingStartTime;

	private String parentChannelId;

	public NewsParser() {
		super();
	}

	public NewsParser(String parentChannelId) {
		super();
		this.parentChannelId = parentChannelId;
	}

	@Override
	public void startDocument() throws SAXException {
		parsingStartTime = SystemClock.elapsedRealtime();
	}

	@Override
	public void endDocument() throws SAXException {
		Log.i(getClass().getName(), "XML parsing took " + (SystemClock.elapsedRealtime() - parsingStartTime) / 1000f + " sec");
		Log.i(getClass().getName(), "Have " + news.size() + " news");
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		buffer = new StringBuilder("");

		if (localName.equalsIgnoreCase(TAG_ITEM)) {
			inItem = true;
			item = new NewsFavoritesDto();
			item.setParentChannelId(parentChannelId);
			enclosures = new ArrayList<EnclosureFavoritesDto>();
		} else if (localName.equalsIgnoreCase(TAG_TITLE)) {
			inTitle = true;
		} else if (localName.equalsIgnoreCase(TAG_LINK)) {
			inLink = true;
		} else if (localName.equalsIgnoreCase(TAG_GUID)) {
			inGuid = true;
		} else if (localName.equalsIgnoreCase(TAG_AUTHOR)) {
			inAuthor = true;
		} else if (localName.equalsIgnoreCase(TAG_LAST_BUILD_DATE)) {
			inLastBuildDate = true;
		} else if (localName.equalsIgnoreCase(TAG_CONTENT)) {
			inContent = true;
		} else if (localName.equalsIgnoreCase(TAG_COMMENTS_LINK)) {
			inCommentsLink = true;
		} else if (localName.equalsIgnoreCase(TAG_PUBDATE) || localName.equalsIgnoreCase(TAG_PUBLISHED)) {
			inPubdate = true;
		} else if (localName.equalsIgnoreCase(TAG_DESCRIPTION)) {
			inDescription = true;
		} else if (localName.equalsIgnoreCase(TAG_ENCLOSURE)) {
			inEnclosure = true;
			enclosure = new EnclosureFavoritesDto();

			if (attributes.getIndex(ATTR_MIME_TYPE) != -1) {
				enclosure.setMimeType(attributes.getValue(ATTR_MIME_TYPE));
			}
			if (attributes.getIndex(ATTR_URL) != -1) {
				enclosure.setUrl(attributes.getValue(ATTR_URL));
			}
			if (attributes.getIndex(ATTR_LENGTH) != -1) {
				enclosure.setLength(Long.parseLong(attributes.getValue(ATTR_LENGTH)));
			}
		} else if (localName.equalsIgnoreCase(TAG_PROPERTY)) {
			inProperty = true;
			if (attributes.getIndex(ATTR_KEY) != -1) {
				currentPropertyKey = attributes.getValue(ATTR_KEY);
			}
		} else if (localName.equalsIgnoreCase(TAG_RELATED_ARTICLE)) {
			inRelatedArticle = true;
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {

		if (inItem) {
			if (inTitle) {
				item.setTitle(buffer.toString());
			} else if (inLink) {
				item.setLink(buffer.toString());
			} else if (inGuid) {
				item.setGuid(buffer.toString());
			} else if (inAuthor) {
				item.setAuthor(buffer.toString());
			} else if (inPubdate) {
				item.setPubDate(buffer.toString());
			} else if (inLastBuildDate) {
				item.setLastBuildDate(buffer.toString());
			} else if (inDescription) {
				item.setDescription(buffer.toString());
			} else if (inContent) {
				item.setContent(buffer.toString());
			} else if (inCommentsLink) {
				item.setCommentsLink(buffer.toString());
			} else if (inEnclosure) {
				if (inProperty) {
					enclosure.setProperty(currentPropertyKey, buffer.toString());
				} else if (inRelatedArticle) {
					enclosure.setRelatedArticleGuid(buffer.toString());
				}
			}
		}
		if (localName.equalsIgnoreCase(TAG_ITEM)) {
			inItem = false;
			item.setEnclosures(enclosures);
			for (EnclosureFavoritesDto enc : item.getEnclosures()) {
				enc.setParentChannelId(item.getGuid());
			}
			news.add(item);
		} else if (localName.equalsIgnoreCase(TAG_TITLE)) {
			inTitle = false;
		} else if (localName.equalsIgnoreCase(TAG_LINK)) {
			inLink = false;
		} else if (localName.equalsIgnoreCase(TAG_GUID)) {
			inGuid = false;
		} else if (localName.equalsIgnoreCase(TAG_AUTHOR)) {
			inAuthor = false;
		} else if (localName.equalsIgnoreCase(TAG_LAST_BUILD_DATE)) {
			inLastBuildDate = false;
		} else if (localName.equalsIgnoreCase(TAG_CONTENT)) {
			inContent = false;
		} else if (localName.equalsIgnoreCase(TAG_COMMENTS_LINK)) {
			inCommentsLink = false;
		} else if (localName.equalsIgnoreCase(TAG_PUBDATE) || localName.equalsIgnoreCase(TAG_PUBLISHED)) {
			inPubdate = false;
		} else if (localName.equalsIgnoreCase(TAG_DESCRIPTION)) {
			inDescription = false;
		} else if (localName.equalsIgnoreCase(TAG_ENCLOSURE)) {
			inEnclosure = false;
			enclosures.add(enclosure);
		} else if (localName.equalsIgnoreCase(TAG_PROPERTY)) {
			inProperty = false;
		} else if (localName.equalsIgnoreCase(TAG_RELATED_ARTICLE)) {
			inRelatedArticle = false;
		}
	}

	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		buffer.append(String.valueOf(ch, start, length));
	}

	/**
	 * Method used to fetch news associated with given channel
	 * 
	 * @return List containing news details
	 */
	public List<NewsFavoritesDto> getNews() {
		return news;
	}

}
